home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / c / library / dos / communic / pcmail / main / gpres.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  6.5 KB  |  226 lines

  1. /*++
  2. /* NAME
  3. /*    gpres.c 3
  4. /* SUMMARY
  5. /*    g-protocol general interface
  6. /* PROJECT
  7. /*    pc-mail
  8. /* PACKAGE
  9. /*    cico
  10. /* SYNOPSIS
  11. /*    int gopen(fd);
  12. /*    int fd;
  13. /*
  14. /*    int gwrite(fd,buf,len)
  15. /*    int fd,len;
  16. /*    char *buf;
  17. /*
  18. /*    int gread(fd,buf,len)
  19. /*    int fd,len;
  20. /*    char *buf;
  21. /*
  22. /*    int gclose(fd)
  23. /*    int fd;
  24. /* DESCRIPTION
  25. /*    The functions in this module present an interface that closely
  26. /*    resembles the unix kernel i/o interface.
  27. /*
  28. /*    gopen() handles the initial message exchange. fd should be
  29. /*    connected to a tty line. gopen() normally returns a zero value.
  30. /*
  31. /*    gwrite() returns the number of bytes `written' to the remote system.
  32. /*    It should be considered an error if this is not equal to the number
  33. /*    of bytes requested.
  34. /*    A zero-length write should be used to indicate EOF during file transfer.
  35. /*
  36. /*    gread() returns the requested number of bytes or the number of
  37. /*    bytes sent by the remote system, whichever is smaller.
  38. /*    A zero-length read indicates EOF during file transfer.
  39. /*
  40. /*    gclose() shuts the protocol down, but does not otherwise change
  41. /*    communications line parameters. It normally returns a zero value.
  42. /* FUNCTIONS AND MACROS
  43. /*    galloc(), gfree(), gsproto(), grproto()
  44. /* DIAGNOSTICS
  45. /*    All functions return -1 in case of unrecoverable problems.
  46. /* BUGS
  47. /*    All g protocol routines assume that the XON/XOFF flow control
  48. /*    has been turned off.
  49. /*    Some parts of the code rely on 8-bit bytes, 16-bit short integers.
  50. /* AUTHOR(S)
  51. /*    W.Z. Venema
  52. /*    Eindhoven University of Technology
  53. /*    Department of Mathematics and Computer Science
  54. /*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  55. /* CREATION DATE
  56. /*    Sun Apr 19 12:41:37 GMT+1:00 1987
  57. /* LAST MODIFICATION
  58. /*    90/01/22 13:01:43
  59. /* VERSION/RELEASE
  60. /*    2.1
  61. /*--*/
  62.  
  63. #include <setjmp.h>
  64. #include "gp.h"
  65.  
  66. /* local and forward declarations */
  67.  
  68. static jmp_buf failbuf;
  69. static void gpeek(),gpoke(),memcpy();
  70.  
  71. /* gfail - exception handling */
  72.  
  73. void gfail()
  74. {
  75.     longjmp(failbuf,1);
  76. }
  77.  
  78. /* gopen - not quite an analogon of unix open(2) */
  79.  
  80. int gopen(fd)
  81. int fd;
  82. {
  83.     return(ginit(fd));        /* do packet stuff elsewhere */
  84. }
  85.  
  86. /* gwrite - g-protocol analogon of unix write(2) */
  87.  
  88. gwrite(fd,data,len)
  89. int fd,len;
  90. char *data;
  91. {
  92.     /* set up exception handling */
  93.  
  94.     if (setjmp(failbuf))            /* in case gsproto fails */
  95.     return(FAIL);                /* it just did */
  96.  
  97.     /* handle special case of zero-length writes separately */
  98.  
  99.     if (len <= 0) {                /* end-of-file message */
  100.     register Packet *pk = galloc();        /* allocate output packet */
  101.     gpoke(pk,data,len);            /* make null-data packet */
  102.     gsproto(fd,pk);                /* send to other side */
  103.     } else {                    /* true data message */
  104.     register int shot;            /* quantum size */
  105.     register int rest;            /* amount left to do */
  106.     for (rest = len; rest > 0; rest -= shot,data += shot) {
  107.         register Packet *pk = galloc();    /* allocate output packet */
  108.         gpoke(pk,data,shot = MIN(pk->len,rest));/* fill the packet */
  109.         gsproto(fd,pk);
  110.     }
  111.     }
  112.     return(len);                /* no problems detected */
  113. }
  114.  
  115. /* gread - g-protocol analogon of unix read(2) */
  116.  
  117. gread(fd,data,len)
  118. int fd,len;
  119. char *data;
  120. {
  121.     static Packet *pk;                /* our byte stock */
  122.     register int igot;                /* our return value */
  123.  
  124.     /* set up exception handling */
  125.  
  126.     if (setjmp(failbuf))            /* in case grproto fails */
  127.     return(FAIL);                /* it just did */
  128.  
  129.     /* if no bytes in stock, get some fresh ones and see how much we got */
  130.  
  131.     if (pk == 0 || pk->segl <= 0)        /* we are out of data */
  132.     gpeek(pk = grproto(fd));        /* get fresh packet */
  133.  
  134.     /* return as many bytes as asked, or as in stock, whichever is less */
  135.  
  136.     if ((igot = MIN(len,pk->segl)) > 0) {
  137.     memcpy(data,pk->segp,igot);        /* copy to caller's buffer */
  138.     pk->segp += igot;            /* update stock pointer */
  139.     pk->segl -= igot;            /* update stock count */
  140.     }
  141.     if (pk->segl <= 0)                /* if we exhausted the stock */
  142.     gfree(pk);                /* release packet */
  143.     return(igot);                /* no problems detected */
  144. }
  145.  
  146. /* gclose - turn g protocol off */
  147.  
  148. gclose(fd)
  149. int fd;
  150. {
  151.     return(gfinit(fd));                /* not here! */
  152. }
  153.  
  154. /* 
  155. * "Each transmitter is constrained to observe the maximum data segment"
  156. * "size established during initial synchronization by the receiver that"
  157. * "it sends to. (...) `short' packets have zero or more data bytes but less"
  158. * "than the maximum. The first one or two bytes of the data segment of"
  159. * "a short packet are `count' bytes that indicate the difference between"
  160. * "the maximum size and the number of bytes in the short segment. If the"
  161. * "difference is less than 127, one count byte is used. If the difference"
  162. * "exceeds 127, then the low-order seven bits of the difference are put"
  163. * "in the first data byte and the remaining high-order bit is set as an"
  164. * "indication that the remaining bits of the difference are in the second"
  165. * "byte.
  166. */
  167.  
  168. /* gpoke - prepare packet for transmission */
  169.  
  170. static void gpoke(pk,data,len)
  171. register Packet *pk;
  172. int len;
  173. char *data;
  174. {
  175.     register int diff = pk->len-len;        /* packet/data size mismatch */
  176.  
  177.     pk->segp = pk->data;            /* set up write pointer */
  178.     pk->segl = len;                /* actual segment length */
  179.     if (diff < 0 || len < 0) {
  180.     DEBUG(7,"gpoke: trouble\n","");        /* something very wrong */
  181.     gfail();
  182.     /* NOTREACHED */
  183.     } else if (diff == 0) {
  184.     pk->c = DATA;                /* long data segment */
  185.     } else if (diff <= 127) {
  186.     pk->c = SHORT;                /* short data segment */
  187.     *pk->segp++ = diff;            /* one difference byte */
  188.     } else if (diff > 127) {
  189.     pk->c = SHORT;                /* tiny data segment */
  190.     *pk->segp++ = diff|0200;        /* two difference bytes */
  191.     *pk->segp++ = diff>>7;
  192.     }
  193.     memcpy(pk->segp,data,pk->segl);        /* copy data into packet */
  194. }
  195.  
  196. /* gpeek - prepare newly packet for reading */
  197.  
  198. static void gpeek(pk)
  199. register Packet *pk;
  200. {
  201.     register int diff;
  202.  
  203.     pk->segp = pk->data;            /* set up read pointer */
  204.     if (TYPE(pk->c) == DATA) {
  205.     diff = 0;                /* long data segment */
  206.     } else if (TYPE(pk->c) != SHORT) {
  207.     DEBUG(7,"gread: trouble\n","");        /* something funny */
  208.     gfail();
  209.     /* NOTREACHED */
  210.     } else if ((diff = *pk->segp++&0377)&0200) {/* short data segment */
  211.     diff = (diff&0177)|((*pk->segp++&0377)<<7);
  212.     }
  213.     pk->segl = pk->len-diff;            /* actual segment size */
  214.     DEBUG(9,"rcv: data %d bytes\n",pk->segl);
  215. }
  216.  
  217. /* memcpy - not-so-efficient implementation */
  218.  
  219. static void memcpy(dst,src,len)
  220. register char *dst,*src;
  221. register int len;
  222. {
  223.     while (len-- > 0)
  224.     *dst++ = *src++;
  225. }
  226.